<?php

namespace WeForge\Runtime\Fpm;

use Illuminate\Support\Collection;
use Swoole\FastCGI\HttpRequest;
use Swoole\Http\Request;

class FpmRequest
{
    /**
     * The incoming request instance.
     *
     * @var \Swoole\Http\Request
     */
    protected $request;

    /**
     * The fastcgi http request instance.
     *
     * @var \Swoole\FastCGI\HttpRequest
     */
    protected $fastCgiRequest;

    /**
     * Create a new instance.
     *
     * @param \Swoole\Http\Request $request
     */
    public function __construct(Request $request)
    {
        $this->request = $request;

        $this->ensureBodyIsSet();
        $this->ensureRequestIdIsSet();
        $this->ensureContentTypeIsSet();
        $this->ensureCookieHeaderIsSet();
    }

    /**
     * Create a new FpmRequest from Swoole HTTP request.
     *
     * @param  \Swoole\Http\Request $request
     *
     * @return static
     */
    public static function createFromRequest(Request $request)
    {
        $instance = new static($request);

        $instance->withHeaders($request->header);
        $instance->withScriptName('httpHandler.php');
        $instance->withMethod($request->server['request_method']);
        $instance->withRequestUri($request->server['request_uri']);
        $instance->withQueryString($request->server['query_string'] ?? '');
        $instance->withParam('SERVER_NAME', $request->header['host'] ?? 'localhost');

        return $instance;
    }

    /**
     * Ensure the server variables contain a content type.
     *
     * @return void
     */
    protected function ensureContentTypeIsSet()
    {
        $this->withParam('CONTENT_TYPE', $this->request->header['content-type'] ?? '');
    }

    /**
     * Ensure the server variables contain a request id.
     *
     * @return void
     */
    protected function ensureRequestIdIsSet()
    {
        if (! isset($this->request->header['x-fc-request-id'])) {
            return;
        }

        $this->withParam('FC_REQUEST_ID', $this->request->header['x-fc-request-id']);
    }

    /**
     * Ensure the request body is set.
     *
     * @return void
     */
    protected function ensureBodyIsSet()
    {
        if (! is_null($this->request->post)) {
            $this->withBody($this->request->post);
        } else {
            $this->withBody($this->request->getContent());
        }
    }

    /**
     * Ensure the cookie header is set.
     *
     * @return \Swoole\FastCGI\HttpRequest
     */
    protected function ensureCookieHeaderIsSet()
    {
        return $this->withHeader('Cookie', Collection::make($this->request->cookie)->map(function ($value, $name) {
            return $name.'='.$value;
        })->flatten()->implode('; '));
    }

    /**
     * Create a new HttpRequest instance.
     *
     * @return \Swoole\FastCGI\HttpRequest
     */
    protected function fastCgiHttpRequest()
    {
        return $this->fastCgiRequest ?: $this->fastCgiRequest = new HttpRequest;
    }

    /**
     * @param  string $method
     * @param  array $parameters
     *
     * @return \Swoole\FastCGI\HttpRequest
     */
    public function __call($method, $parameters)
    {
        return $this->fastCgiHttpRequest()->{$method}(...$parameters);
    }
}
